package com.lib76.socket;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.lang.StringUtils;

import com.lib76.socket.message.ByteSocketMessage;
import com.lib76.socket.message.JsonSocketMessage;
import com.lib76.socket.message.SpaceSocketMessage;
import com.lib76.socket.model.SocketMessage;
import com.lib76.socket.model.protocol.SocketProtocol;
import com.lib76.socket.model.protocol.SocketProtocolGroup;
import com.lib76.socket.model.protocol.SocketProtocolObject;

public class SocketMessageProtocolManager {

	private final static ConcurrentMap<String, SocketProtocolGroup> SOCKET_PROTOCOL_STORE = new ConcurrentHashMap<String, SocketProtocolGroup>();

	
	//==============������ط���==============//
	
	public static boolean addSocketProtocolGroup(SocketProtocolGroup protocolGroup){
		if(protocolGroup != null && StringUtils.isNotBlank(protocolGroup.getVersion())){
			SOCKET_PROTOCOL_STORE.put(protocolGroup.getVersion(), protocolGroup);
			return true;
		}
		return false;
	}
	
	public static void removeSocketProtocolGroup(String version){
		SOCKET_PROTOCOL_STORE.remove(version);
	}
	
	public static SocketProtocolGroup getSocketProtocolGroup(String version){
		return SOCKET_PROTOCOL_STORE.get(version);
	}
	
	public static SocketProtocol getSocketProtocol(String version,String protocolCode){
		SocketProtocolGroup protocolGroup = getSocketProtocolGroup(version);
		if(protocolGroup != null){
			return protocolGroup.getProtocols().get(protocolCode);
		}
		return null;
	}
	
	//=============��������================//
	
	/**
	 * ����һ��ֻ�б���ͷ��Ϣû�б�������Ϣ�ı��Ķ���
	 * @param protocolGroup
	 * @param direction	���ķ�������ͣ�request��response
	 * @return
	 */
	public static SocketProtocolObject createSocketProtocolObject(SocketProtocolGroup protocolGroup){
		SocketProtocolObject result = new SocketProtocolObject();
		result.setVersion(protocolGroup.getVersion());
		result.setType(protocolGroup.getType());
		result.setHeaderProtocolParameter(protocolGroup.getHeaderParameters());
		result.setHeaderLength(protocolGroup.getHeaderLength());
		return result;
	}
	
	/**
	 * ��ݱ��������ͱ��������ȡ���Ķ���
	 * @param version
	 * @param command
	 * @return	NULL���Ķ���
	 */
	public static SocketProtocolObject createSocketProtocolObject(SocketProtocolGroup protocolGroup,String command){
		for(SocketProtocol protocol : protocolGroup.getProtocols().values()){
			if(protocol.getRequestCommand().equals(command)){
				SocketProtocolObject protocolObject = createSocketProtocolObject(protocolGroup);
				protocolObject.setProtocol(protocol);
				protocolObject.setDirection(Constants.MSG_PROTOCOL_DIRECTION_REQUEST);
				return protocolObject;
			}else if(protocol.getResponseCommand().equals(command)){
				SocketProtocolObject protocolObject = createSocketProtocolObject(protocolGroup);
				protocolObject.setProtocol(protocol);
				protocolObject.setDirection(Constants.MSG_PROTOCOL_DIRECTION_RESPONSE);
				return protocolObject;
			}
		}
		return null;
	}
	
	/**
	 * ��ݱ�����汾�ͱ��Ľṹ������뼰���ĵķ������ͽ�������Ϣ
	 * @param version
	 * @param protocolCode
	 * @param direction
	 * @return
	 */
	public static SocketMessage createSocketMessage(String version,String protocolCode,String direction){
		SocketMessage msg = null;
		if(StringUtils.isNotBlank(version) && StringUtils.isNotBlank(protocolCode)){
			if(StringUtils.isBlank(direction)){direction = Constants.MSG_PROTOCOL_DIRECTION_REQUEST;}
			SocketProtocolGroup protocolGroup = getSocketProtocolGroup(version);
			if(protocolGroup != null){
				SocketProtocol protocol = protocolGroup.getProtocols().get(protocolCode);
				if(protocol != null){
					SocketProtocolObject protocolObject = createSocketProtocolObject(protocolGroup);
					protocolObject.setDirection(direction);
					protocolObject.setType(protocolGroup.getType());
					protocolObject.setProtocol(protocol);
					if(Constants.MSG_PROTOCOL_TYPE_BYTE.equals(protocolGroup.getType())){
						msg = new ByteSocketMessage(protocolObject);
					}else if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(protocolGroup.getType())){
						msg = new JsonSocketMessage(protocolObject);
					}else if(Constants.MSG_PROTOCOL_TYPE_SPACE.equals(protocolGroup.getType())){
						msg = new SpaceSocketMessage(protocolObject);
					}
				}
			}
		}
		return msg;
	}
	
	public static SocketMessage createSocketMessage(String version){
		SocketMessage msg = null;
		if(StringUtils.isNotBlank(version)){
			SocketProtocolGroup protocolGroup = getSocketProtocolGroup(version);
			if(protocolGroup != null){
				SocketProtocolObject protocolObject = createSocketProtocolObject(protocolGroup);
				if(Constants.MSG_PROTOCOL_TYPE_BYTE.equals(protocolGroup.getType())){
					msg = new ByteSocketMessage(protocolObject);
				}else if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(protocolGroup.getType())){
					msg = new JsonSocketMessage(protocolObject);
				}else if(Constants.MSG_PROTOCOL_TYPE_SPACE.equals(protocolGroup.getType())){
					msg = new SpaceSocketMessage(protocolObject);
				}
			}
		}
		return msg;
	}
	
	/**
	 * ��ݱ�����汾�ͱ������ݴ���������Ϣ
	 * @param version
	 * @param message
	 * @return
	 * @throws IOException
	 */
	public static SocketMessage createSocketMessage(String version,Object message) throws Exception{
		SocketMessage msg = null;
		if(StringUtils.isNotBlank(version)){
			SocketProtocolGroup protocolGroup = getSocketProtocolGroup(version);
			if(protocolGroup != null){
				if(Constants.MSG_PROTOCOL_TYPE_BYTE.equals(protocolGroup.getType())){
					msg = new ByteSocketMessage(message);
				}else if(Constants.MSG_PROTOCOL_TYPE_JSON.equals(protocolGroup.getType())){
					msg = new JsonSocketMessage(message);
				}else if(Constants.MSG_PROTOCOL_TYPE_SPACE.equals(protocolGroup.getType())){
					msg = new SpaceSocketMessage(message);
				}
				//��������ͷ
				msg.read(protocolGroup.getHeaderParameters());
				String command = msg.readString(SocketProtocolGroup.COMMAND_FIELD_NAME); //����
        		String direction = msg.readString(SocketProtocolGroup.DIRECTION_FIELD_NAME); //����
        		if(StringUtils.isNotBlank(command)){
        			SocketProtocolObject protocolObject = createSocketProtocolObject(protocolGroup,command);
        			if(protocolObject != null){
        				//����ķ������ѯ�Ĳ�һ�£�����м�����¸��ķ���ֵ
        				if(StringUtils.isNotBlank(direction) && !protocolObject.getDirection().equals(direction)){
        					if(Constants.MSG_PROTOCOL_DIRECTION_REQUEST.equals(direction) 
        							&& protocolObject.getProtocol().getRequestCommand().equals(command)){
        						protocolObject.setDirection(direction);
        					}else if(Constants.MSG_PROTOCOL_DIRECTION_RESPONSE.equals(direction) 
        							&& protocolObject.getProtocol().getResponseCommand().equals(command)){
        						protocolObject.setDirection(direction);
        					}
        				}
        				msg.setProtocolObject(protocolObject);
        			}
        		}
			}
		}
		return msg;
	}
}
